package com.paullorenc.rose.desktop.conversation

import androidx.compose.runtime.mutableStateListOf
import com.paullorenc.rose.desktop.ForwardMessageBus
import com.paullorenc.rose.desktop.IncomingMessageBus
import com.paullorenc.rose.desktop.OutgoingMessageBus
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import java.security.MessageDigest
import kotlin.text.Charsets.UTF_8

// From https://www.samclarke.com/kotlin-hash-strings/
fun sha256(input: String): String {
    val HEX_CHARS = "0123456789ABCDEF"
    val bytes = MessageDigest
        .getInstance("SHA-256")
        .digest(input.toByteArray())
    val result = StringBuilder(bytes.size * 2)
    bytes.forEach {
        val i = it.toInt()
        result.append(HEX_CHARS[i shr 4 and 0x0f])
        result.append(HEX_CHARS[i and 0x0f])
    }
    return result.toString().substring(0,7)
}

object ConversationViewModel {
    private val MAX_SEENMESSAGE_SIZE = 256
    private val _seenMessages = mutableSetOf<String>()
    val seenMessages: Set<String> = _seenMessages
    private val _messages = mutableStateListOf<ConversationItem>()
    val messages: List<ConversationItem> = _messages
    init {
        GlobalScope.launch(Dispatchers.IO) {
            IncomingMessageBus.incoming.collect { str ->
                if(!seenMessages.contains(sha256(str))) {
                    if(seenMessages.size == MAX_SEENMESSAGE_SIZE) {
                        _seenMessages.remove(_seenMessages.last())
                    }
                    _messages.add(ConversationItem(false, str))
                    _seenMessages.add(sha256(str))
                    ForwardMessageBus.postMessage(str)
                }
            }
        }
        GlobalScope.launch(Dispatchers.IO) {
            OutgoingMessageBus.outgoing.collect {
                if(!seenMessages.contains(sha256(it))) {
                    _messages.add(ConversationItem(true, it))
                    _seenMessages.add(sha256(it))
                }
            }
        }
    }
    fun prettyPrint(strL: List<ConversationItem>) {
        for(i in strL) {
            println("element in list ${i.msg}")
        }
    }
    fun add(self: Boolean, str: String) {
        _messages.add(ConversationItem(self, str))
    }
}